using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel;
using System.Windows.Forms;

namespace ICSharpCode.WinFormsUI.Controls.NodeControls
{
	public abstract class BindableControl: NodeControl
	{
		private string _propertyName = "";
		[DefaultValue("")]
		public string DataPropertyName
		{
			get { return _propertyName; }
			set 
			{
				if (_propertyName == null)
					_propertyName = string.Empty;
				_propertyName = value; 
			}
		}

		public object GetValue(NTreeNode node)
		{
			PropertyInfo pi = GetPropertyInfo(node);
			if (pi != null && pi.CanRead)
				return pi.GetValue(node.TagNode, null);
			else
				return null;
		}

		public void SetValue(NTreeNode node, object value)
		{
			PropertyInfo pi = GetPropertyInfo(node);
			if (pi != null && pi.CanWrite)
			{
				try
				{
					pi.SetValue(node.TagNode, value, null);
				}
				catch (TargetInvocationException ex)
				{
					if (ex.InnerException != null)
						throw new ArgumentException(ex.InnerException.Message, ex.InnerException);
					else
						throw new ArgumentException(ex.Message);
				}
			}
		}

        public Type GetPropertyType(NTreeNode node)
		{
			if (node.TagNode != null && !string.IsNullOrEmpty(DataPropertyName))
			{
				Type type = node.TagNode.GetType();
				PropertyInfo pi = type.GetProperty(DataPropertyName);
				if (pi != null)
					return pi.PropertyType;
			}
			return null;
		}

        internal PropertyInfo GetPropertyInfo(NTreeNode node)
		{
			if (node.TagNode != null && !string.IsNullOrEmpty(DataPropertyName))
			{
				Type type = node.TagNode.GetType();
				return type.GetProperty(DataPropertyName);
			}
			return null;
		}

        internal void SetSelfValue(NTreeNode node, bool value)
        {
            PropertyInfo pi = null;
            if (!string.IsNullOrEmpty(DataPropertyName))
                pi = node.GetType().GetProperty(DataPropertyName);

            if (pi != null && pi.CanWrite)
            {
                try
                {
                    pi.SetValue(node, value, null);
                }
                catch (TargetInvocationException ex)
                {
                    if (ex.InnerException != null)
                        throw new ArgumentException(ex.InnerException.Message, ex.InnerException);
                    else
                        throw new ArgumentException(ex.Message);
                }
            }
        }

        public override string ToString()
		{
			if (string.IsNullOrEmpty(DataPropertyName))
				return GetType().Name;
			else
				return string.Format("{0} ({1})", GetType().Name, DataPropertyName);
		}
	}
}
